import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import mean_squared_error, mean_absolute_error
import numpy as np
import joblib

from . import config
from . import data_loader
from . import feature_engineering

def plot_predictions_vs_actuals(test_df: pd.DataFrame, community_id_to_plot: int = 1):
    """
    为指定社区绘制真实值与预测值的对比图，并保存到本地。
    """
    print(f"\n正在为社区 {community_id_to_plot} 生成预测结果可视化图表...")
    
    community_df = test_df[test_df['community_id'] == community_id_to_plot].copy()
    
    if community_df.empty:
        print(f"❌ 错误：在测试集中找不到社区 {community_id_to_plot} 的数据。")
        return

    # 2. 设置整体样式
    sns.set_theme(style="whitegrid")
    plt.figure(figsize=(24, 10)) # 增大画布尺寸

    # 3. 绘制图表，优化线条和标记
    plt.plot(
        community_df['timestamp'], 
        community_df['net_flow'], 
        label='real', 
        color='dodgerblue', 
        marker='o',          # 使用更明显的圆形标记
        markersize=5,        # 标记大小
        linestyle='-', 
        linewidth=2          # 线条宽度
    )
    plt.plot(
        community_df['timestamp'], 
        community_df['prediction'], 
        label='predicted', 
        color='orangered', 
        linestyle='--', 
        linewidth=2.5        # 预测线条稍粗
    )
    
    # 4. 添加图表元素，使用更大的字体
    # plt.title(f'Community {community_id_to_plot}: 真实净流量 vs. 预测净流量', fontproperties=cn_font_title)
    plt.xlabel('Time', fontsize=25)
    plt.ylabel('Net Flow', fontsize=25)

    # 设置坐标轴刻度的字体大小
    plt.xticks(rotation=30, ha='right', fontsize=23)
    plt.yticks(fontsize=23)
    
    # 显示图例，并设置字体
    plt.legend(fontsize=18)
    
    # 添加网格线，使其更清晰
    plt.grid(True, which='both', linestyle='--', linewidth=0.5)
    
    plt.tight_layout()
    
    # 5. 保存图表
    output_path = f"backend/model_train/results/evaluation_community_{community_id_to_plot}.png"
    plt.savefig(output_path, dpi=150) # 提高保存图片的分辨率
    
    print(f"✅ 图表已成功保存到: {output_path}")

def evaluate_model_performance(y_true, y_pred):
    """
    计算并打印模型的评估指标。
    """
    rmse = np.sqrt(mean_squared_error(y_true, y_pred))
    mae = mean_absolute_error(y_true, y_pred)
    
    print("\n--- 模型性能评估 ---")
    print(f"均方根误差 (RMSE): {rmse:.4f}")
    print(f"平均绝对误差 (MAE): {mae:.4f}")
    print("--------------------")


def run_standalone_evaluation(community_id_to_test: int = 1):
    """
    独立运行模型评估的完整流程。
    """
    print("--- 开始独立模型评估流程 ---")
    
    # 1. 加载训练好的模型
    print(f"正在从 {config.MODEL_OUTPUT_PATH} 加载模型...")
    try:
        model = joblib.load(config.MODEL_OUTPUT_PATH)
    except FileNotFoundError:
        print(f"❌ 错误：找不到模型文件。请先运行 train.py 训练并保存模型。")
        return
        
    # 2. 加载并准备测试数据
    df = data_loader.load_all_net_flows_from_redis()
    if df is None:
        return
        
    df = feature_engineering.create_time_features(df)
    df = feature_engineering.create_lag_features(df, config.LAG_WINDOW_SIZE)
    df.dropna(inplace=True)
    
    # 同样使用最后两天的数据作为测试集
    split_date = df['timestamp'].max() - pd.Timedelta(days=2)
    test_df = df[df['timestamp'] >= split_date].copy()
    
    if test_df.empty:
        print("❌ 错误：无法生成测试数据。")
        return
        
    print(f"测试数据准备完成，共 {len(test_df)} 条记录。")
    
    # 3. 在测试集上进行预测
    y_test = test_df['net_flow']
    X_test = test_df.drop(columns=['timestamp', 'net_flow'])
    
    print("正在使用加载的模型进行预测...")
    predictions = model.predict(X_test)
    test_df['prediction'] = predictions
    
    # 4. 调用评估和可视化函数
    evaluate_model_performance(y_test, predictions)
    plot_predictions_vs_actuals(test_df, community_id_to_plot=community_id_to_test)

if __name__ == "__main__":
    # 当这个文件被直接运行时 (python -m backend.model_train.evaluation)，
    # 就执行下面的函数。
    run_standalone_evaluation(community_id_to_test=45)